use util::{self, CargoResult, human, internal, ChainError, Config};
use ops;
-struct Bomb { path: Option<PathBuf> }
-
-impl Drop for Bomb {
- fn drop(&mut self) {
- match self.path.as_ref() {
- Some(path) => { let _ = fs::remove_file(path); }
- None => {}
- }
- }
-}
-
pub fn package(manifest_path: &Path,
config: &Config,
verify: bool,
return Ok(None)
}
- let filename = format!("package/{}-{}.crate", pkg.name(), pkg.version());
- let target_dir = config.target_dir(&pkg);
- let dst = target_dir.join(&filename);
- if fs::metadata(&dst).is_ok() { return Ok(Some(dst)) }
-
- let mut bomb = Bomb { path: Some(dst.clone()) };
+ let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
+ let dir = config.target_dir(&pkg).join("package");
+ let dst = dir.join(&filename);
+ if fs::metadata(&dst).is_ok() {
+ return Ok(Some(dst))
+ }
+ // Package up and test a temporary tarball and only move it to the final
+ // location if it actually passes all our tests. Any previously existing
+ // tarball can be assumed as corrupt or invalid, so we just blow it away if
+ // it exists.
try!(config.shell().status("Packaging", pkg.package_id().to_string()));
- try!(tar(&pkg, &src, config, &dst).chain_error(|| {
+ let tmp_dst = dir.join(format!(".{}", filename));
+ let _ = fs::remove_file(&tmp_dst);
+ try!(tar(&pkg, &src, config, &tmp_dst, &filename).chain_error(|| {
human("failed to prepare local package for uploading")
}));
if verify {
- try!(run_verify(config, &pkg, &dst).chain_error(|| {
+ try!(run_verify(config, &pkg, &tmp_dst).chain_error(|| {
human("failed to verify package tarball")
}))
}
- Ok(Some(bomb.path.take().unwrap()))
+ try!(fs::rename(&tmp_dst, &dst).chain_error(|| {
+ human("failed to move temporary tarball into final location")
+ }));
+ Ok(Some(dst))
}
// check that the package has some piece of metadata that a human can
Ok(())
}
-fn tar(pkg: &Package, src: &PathSource, config: &Config,
- dst: &Path) -> CargoResult<()> {
-
+fn tar(pkg: &Package,
+ src: &PathSource,
+ config: &Config,
+ dst: &Path,
+ filename: &str) -> CargoResult<()> {
if fs::metadata(&dst).is_ok() {
bail!("destination already exists: {}", dst.display())
}
let tmpfile = try!(File::create(dst));
// Prepare the encoder and its header
- let filename = Path::new(dst.file_name().unwrap());
+ let filename = Path::new(filename);
let encoder = GzBuilder::new().filename(try!(util::path2bytes(filename)))
.write(tmpfile, Compression::Best);